package com.ics.atable.chat.service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ics.atable.chat.config.DynamicDataSourceManager;
import com.ics.atable.chat.mapper.DbConfigMapper;
import com.ics.atable.chat.model.dto.DbConfigDTO;
import com.ics.atable.chat.model.entity.DbConfig;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 数据库配置管理服务
 * 
 * 负责数据库配置的增删改查操作
 * 同时管理动态数据源的创建和销毁
 * 
 * @author Chawu
 */
@Slf4j
@Service
public class DbConfigService extends ServiceImpl<DbConfigMapper, DbConfig> {
    
    @Autowired
    private DynamicDataSourceManager dynamicDataSourceManager;
    
    /**
     * 添加数据库配置
     * 
     * @param dto 配置DTO
     * @return 是否成功
     */
    @Transactional(rollbackFor = Exception.class)
    public boolean addDbConfig(DbConfigDTO dto) {
        try {
            // 检查数据源名称是否已存在
            if (isNameExists(dto.getName())) {
                throw new RuntimeException("数据源名称已存在: " + dto.getName());
            }
            
            // 创建实体对象
            DbConfig entity = new DbConfig();
            BeanUtils.copyProperties(dto, entity);
            entity.setCreateTime(LocalDateTime.now());
            entity.setUpdateTime(LocalDateTime.now());
            
            // 保存到数据库
            boolean saved = save(entity);
            if (!saved) {
                throw new RuntimeException("保存数据库配置失败");
            }
            
            // 如果配置是启用的，则创建数据源
            if (entity.getEnabled()) {
                try {
                    dynamicDataSourceManager.addDataSource(entity);
                    log.info("成功添加并初始化数据源: {}", entity.getName());
                } catch (Exception e) {
                    log.error("初始化数据源失败: {}, 错误信息: {}", entity.getName(), e.getMessage(), e);
                    // 如果数据源初始化失败，可以选择禁用该配置
                    entity.setEnabled(false);
                    updateById(entity);
                    throw new RuntimeException("数据源初始化失败: " + e.getMessage());
                }
            }
            
            return true;
            
        } catch (Exception e) {
            log.error("添加数据库配置失败: {}", e.getMessage(), e);
            throw e;
        }
    }
    
    /**
     * 更新数据库配置
     * 
     * @param dto 配置DTO
     * @return 是否成功
     */
    @Transactional(rollbackFor = Exception.class)
    public boolean updateDbConfig(DbConfigDTO dto) {
        try {
            if (dto.getId() == null) {
                throw new RuntimeException("更新时ID不能为空");
            }
            
            // 查询原配置
            DbConfig oldEntity = getById(dto.getId());
            if (oldEntity == null) {
                throw new RuntimeException("配置不存在: " + dto.getId());
            }
            
            // 检查名称是否被其他记录使用
            if (!oldEntity.getName().equals(dto.getName()) && isNameExists(dto.getName())) {
                throw new RuntimeException("数据源名称已存在: " + dto.getName());
            }
            
            // 更新实体对象
            DbConfig entity = new DbConfig();
            BeanUtils.copyProperties(dto, entity);
            entity.setUpdateTime(LocalDateTime.now());
            
            // 更新数据库
            boolean updated = updateById(entity);
            if (!updated) {
                throw new RuntimeException("更新数据库配置失败");
            }
            
            // 处理数据源
            handleDataSourceUpdate(oldEntity, entity);
            
            return true;
            
        } catch (Exception e) {
            log.error("更新数据库配置失败: {}", e.getMessage(), e);
            throw e;
        }
    }
    
    /**
     * 删除数据库配置
     * 
     * @param id 配置ID
     * @return 是否成功
     */
    @Transactional(rollbackFor = Exception.class)
    public boolean deleteDbConfig(Long id) {
        try {
            // 查询配置
            DbConfig entity = getById(id);
            if (entity == null) {
                throw new RuntimeException("配置不存在: " + id);
            }
            
            // 先移除数据源
            if (dynamicDataSourceManager.containsDataSource(entity.getName())) {
                dynamicDataSourceManager.removeDataSource(entity.getName());
                log.info("成功移除数据源: {}", entity.getName());
            }
            
            // 删除数据库记录
            boolean deleted = removeById(id);
            if (!deleted) {
                throw new RuntimeException("删除数据库配置失败");
            }
            
            return true;
            
        } catch (Exception e) {
            log.error("删除数据库配置失败: {}", e.getMessage(), e);
            throw e;
        }
    }
    
    /**
     * 根据ID查询配置
     * 
     * @param id 配置ID
     * @return 配置DTO
     */
    public DbConfigDTO getDbConfigById(Long id) {
        DbConfig entity = getById(id);
        if (entity == null) {
            return null;
        }
        
        DbConfigDTO dto = new DbConfigDTO();
        BeanUtils.copyProperties(entity, dto);
        return dto;
    }
    
    /**
     * 根据名称查询配置
     * 
     * @param name 配置名称
     * @return 配置DTO
     */
    public DbConfigDTO getDbConfigByName(String name) {
        DbConfig entity = baseMapper.selectByName(name);
        if (entity == null) {
            return null;
        }
        
        DbConfigDTO dto = new DbConfigDTO();
        BeanUtils.copyProperties(entity, dto);
        return dto;
    }
    
    /**
     * 查询所有配置
     * 
     * @return 配置列表
     */
    public List<DbConfigDTO> getAllDbConfigs() {
        List<DbConfig> entities = list();
        return entities.stream()
                .map(entity -> {
                    DbConfigDTO dto = new DbConfigDTO();
                    BeanUtils.copyProperties(entity, dto);
                    return dto;
                })
                .collect(Collectors.toList());
    }
    
    /**
     * 查询启用的配置
     * 
     * @return 启用的配置列表
     */
    public List<DbConfigDTO> getEnabledDbConfigs() {
        List<DbConfig> entities = baseMapper.selectEnabledConfigs();
        return entities.stream()
                .map(entity -> {
                    DbConfigDTO dto = new DbConfigDTO();
                    BeanUtils.copyProperties(entity, dto);
                    return dto;
                })
                .collect(Collectors.toList());
    }
    
    /**
     * 启用/禁用配置
     * 
     * @param id 配置ID
     * @param enabled 启用状态
     * @return 是否成功
     */
    @Transactional(rollbackFor = Exception.class)
    public boolean updateEnabled(Long id, Boolean enabled) {
        try {
            // 查询配置
            DbConfig entity = getById(id);
            if (entity == null) {
                throw new RuntimeException("配置不存在: " + id);
            }
            
            // 更新启用状态
            entity.setEnabled(enabled);
            entity.setUpdateTime(LocalDateTime.now());
            boolean updated = updateById(entity);
            if (!updated) {
                throw new RuntimeException("更新启用状态失败");
            }
            
            // 处理数据源
            if (enabled) {
                // 启用：创建数据源
                if (!dynamicDataSourceManager.containsDataSource(entity.getName())) {
                    dynamicDataSourceManager.addDataSource(entity);
                    log.info("成功启用数据源: {}", entity.getName());
                }
            } else {
                // 禁用：移除数据源
                if (dynamicDataSourceManager.containsDataSource(entity.getName())) {
                    dynamicDataSourceManager.removeDataSource(entity.getName());
                    log.info("成功禁用数据源: {}", entity.getName());
                }
            }
            
            return true;
            
        } catch (Exception e) {
            log.error("更新启用状态失败: {}", e.getMessage(), e);
            throw e;
        }
    }
    
    /**
     * 测试数据源连接
     * 
     * @param dto 配置DTO
     * @return 是否连接成功
     */
    public boolean testConnection(DbConfigDTO dto) {
        try {
            // 创建临时数据源进行测试
            DbConfig tempEntity = new DbConfig();
            BeanUtils.copyProperties(dto, tempEntity);
            
            // 创建临时数据源
            dynamicDataSourceManager.createDataSource(tempEntity);
            
            // 测试连接
            boolean connected = dynamicDataSourceManager.testConnection(dto.getName());
            
            // 清理临时数据源
            dynamicDataSourceManager.removeDataSource(dto.getName());
            
            return connected;
            
        } catch (Exception e) {
            log.error("测试连接失败: {}", e.getMessage(), e);
            return false;
        }
    }
    
    /**
     * 检查名称是否已存在
     * 
     * @param name 名称
     * @return 是否存在
     */
    private boolean isNameExists(String name) {
        QueryWrapper<DbConfig> wrapper = new QueryWrapper<>();
        wrapper.eq("name", name);
        return count(wrapper) > 0;
    }
    
    /**
     * 处理数据源更新
     * 
     * @param oldEntity 原配置
     * @param newEntity 新配置
     */
    private void handleDataSourceUpdate(DbConfig oldEntity, DbConfig newEntity) {
        try {
            // 如果名称发生变化，需要先移除旧的数据源
            if (!oldEntity.getName().equals(newEntity.getName())) {
                if (dynamicDataSourceManager.containsDataSource(oldEntity.getName())) {
                    dynamicDataSourceManager.removeDataSource(oldEntity.getName());
                }
            }
            
            // 如果新配置是启用的，创建数据源
            if (newEntity.getEnabled()) {
                if (!dynamicDataSourceManager.containsDataSource(newEntity.getName())) {
                    dynamicDataSourceManager.addDataSource(newEntity);
                    log.info("成功更新并初始化数据源: {}", newEntity.getName());
                }
            } else {
                // 如果新配置是禁用的，移除数据源
                if (dynamicDataSourceManager.containsDataSource(newEntity.getName())) {
                    dynamicDataSourceManager.removeDataSource(newEntity.getName());
                    log.info("成功禁用数据源: {}", newEntity.getName());
                }
            }
            
        } catch (Exception e) {
            log.error("处理数据源更新失败: {}", e.getMessage(), e);
            throw new RuntimeException("数据源更新失败: " + e.getMessage());
        }
    }
}
